/**
 * @list.cpp
 * This file is part of FEGRF.
 * 
 * FEGRF is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * See LICENSE file in main folder for more information.
 */

#include <wx/wxprec.h>

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

#include "list.h"

#if defined( __WXMSW__ ) && defined( _DEBUG )
#include <wx/msw/msvcrt.h>
#endif

BEGIN_EVENT_TABLE(MyDataViewCtrl, wxWindow)
	EVT_DATAVIEW_SELECTION_CHANGED(LIST_GRF, MyDataViewCtrl::OnRefresh)
	EVT_DATAVIEW_ITEM_START_EDITING(LIST_GRF, MyDataViewCtrl::OnEditingStart)
	EVT_DATAVIEW_ITEM_EDITING_DONE(LIST_GRF, MyDataViewCtrl::OnEditingDone)
	EVT_SIZE(MyDataViewCtrl::OnResize)
	EVT_DATAVIEW_COLUMN_SORTED(LIST_GRF, MyDataViewCtrl::OnSorted)
END_EVENT_TABLE()

int CompareName(const MyData** arg1, const MyData** arg2)  { return ((*arg1)->name.CmpNoCase((*arg2)->name)); }
int CompareNameX(const MyData** arg1, const MyData** arg2) { return ((*arg2)->name.CmpNoCase((*arg1)->name)); }
int CompareType(const MyData** arg1, const MyData** arg2)  { return ((*arg1)->type.CmpNoCase((*arg2)->type)); }
int CompareTypeX(const MyData** arg1, const MyData** arg2) { return ((*arg2)->type.CmpNoCase((*arg1)->type)); }
int CompareSize(const MyData** arg1, const MyData** arg2)  { return ((*arg1)->size - (*arg2)->size); }
int CompareSizeX(const MyData** arg1, const MyData** arg2) { return ((*arg2)->size - (*arg1)->size); }
int ComparePack(const MyData** arg1, const MyData** arg2)  { return ((*arg1)->pack - (*arg2)->pack); }
int ComparePackX(const MyData** arg1, const MyData** arg2) { return ((*arg2)->pack - (*arg1)->pack); }

MyListModel::MyListModel(MainFrame *main_frame)
	:wxDataViewVirtualListModel(0)
{
	parent = main_frame;
}

void MyListModel::GetValueByRow(wxVariant &variant, unsigned int row, unsigned int column) const
{
	if (row >= parent->m_grf_data->GetCount())
		return;
	MyData *data = parent->m_grf_data->Item(row)->GetData();
	switch (column) {
		case COL_NAME:
			switch (parent->m_grf_list->enc_type) {
				case ENC_ANSI:  // ASCII
					variant = data->name;
					break;
				case ENC_EUC_KR: // Convert to EUC_KR (Korean's Font? Laggy sometimes)
					variant = wxString(data->name.To8BitData(), wxCSConv(wxFONTENCODING_EUC_KR));
					break;
				case ENC_LOCAL:  // Depend on your computer locale (Use this instead of ENC_EUC_KR if your computer run in Korean)
					variant = wxString(data->name.To8BitData(), wxConvLocal);
					break;
			} break;
		case COL_TYPE:
			variant = _(data->type);
			break;
		case COL_SIZE:
			variant = wxString::Format("%d", data->size);
			break;
		case COL_PACK:
			variant = wxString::Format("%d", data->pack);
			break;
	}
}

bool MyListModel::GetAttrByRow(unsigned int row, unsigned int column, wxDataViewItemAttr &attr) const
{
	return false;
}

bool MyListModel::SetValueByRow(const wxVariant &variant, unsigned int row, unsigned int column)
{
	return false;
}

MyDataViewCtrl::MyDataViewCtrl(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style)
	:wxDataViewCtrl(parent, id, pos, size, style)
{
	//Variable
	sort_name =
	sort_type =
	sort_size =
	sort_pack = false;
	enc_type  = ENC_LOCAL;
	m_editing = false;

	//Model
	listmodel = new MyListModel((MainFrame*)parent);
	AssociateModel(listmodel.get());

	//Header
	AppendTextColumn("Name", COL_NAME, wxDATAVIEW_CELL_EDITABLE, -1, wxALIGN_LEFT, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
	AppendTextColumn("Type", COL_TYPE, wxDATAVIEW_CELL_INERT, 110, wxALIGN_LEFT, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
	AppendTextColumn("Size", COL_SIZE, wxDATAVIEW_CELL_INERT, 70, wxALIGN_LEFT, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE);
	AppendTextColumn("Pack", COL_PACK, wxDATAVIEW_CELL_INERT, 70, wxALIGN_LEFT, wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_SORTABLE);
}

wxDataViewItem MyDataViewCtrl::GetItem(int row)
{
	return listmodel->GetItem(row);
}

int MyDataViewCtrl::GetRow(wxDataViewItem item)
{
	return listmodel->GetRow(item);
}

void MyDataViewCtrl::Resize(int size)
{
	listmodel->Reset(size);
}

void MyDataViewCtrl::OnRefresh(wxDataViewEvent &WXUNUSED(event))
{
	Refresh(); //Prevent glitch..
}

void MyDataViewCtrl::StartEdit(wxDataViewItem item)
{
	m_editing = true;
	StartEditor(item, 0);
}

void MyDataViewCtrl::OnEditingStart(wxDataViewEvent &event)
{
	if (!m_editing) //Disable renaming with "Clicking" method
		event.Veto();
}

void MyDataViewCtrl::OnEditingDone(wxDataViewEvent &event)
{
	m_editing = false;
	if (!event.IsEditCancelled()) {
		MainFrame *parent = (MainFrame*)GetParent();
		MyData *data = parent->m_grf_data->Item(GetRow(event.GetItem()))->GetData();
		wxString new_name = event.GetValue().GetString();
		wxString old_name = data->name;
		if (old_name == new_name)
			return;

		data->name = new_name;
		if (!new_name.StartsWith(_("data\\"))) {
			if (wxMessageBox(_("File name should be started with \"data\\\".\nDo you want to continue?"), _("Warning"), wxYES_NO) == wxNO) {
				data->name = old_name;
				StartEdit(event.GetItem());
				return;
			}
		}
		GrfNode *grf_node = grf_get_file(parent->m_grf_handle, old_name.c_str());
		grf_file_rename(grf_node, new_name.c_str());
		data->type = GetExtension(new_name.c_str());
	}
}

void MyDataViewCtrl::OnSorted(wxDataViewEvent &event)
{
	event.Skip(true);

	MainFrame *parent = (MainFrame*) GetParent();
	if (parent->m_grf_data->IsEmpty())
		return;

	int col = event.GetColumn();
	switch (col) {
		case COL_NAME:
			sort_type = sort_size = sort_pack = false;
			if (!sort_name) {
				sort_name = true;
				parent->m_grf_data->Sort(CompareName);
			} else {
				sort_name = false;
				parent->m_grf_data->Sort(CompareNameX);
			} break;
		case COL_TYPE:
			sort_name = sort_size = sort_pack = false;
			if (!sort_type) {
				sort_type = true;
				parent->m_grf_data->Sort(CompareType);
			} else {
				sort_type = false;
				parent->m_grf_data->Sort(CompareTypeX);
			} break;
		case COL_SIZE:
			sort_name = sort_type = sort_pack = false;
			if (!sort_size) {
				sort_size = true;
				parent->m_grf_data->Sort(CompareSize);
			} else {
				sort_size = false;
				parent->m_grf_data->Sort(CompareSizeX);
			} break;
		case COL_PACK:
			sort_name = sort_type = sort_size = false;
			if (!sort_pack) {
				sort_pack = true;
				parent->m_grf_data->Sort(ComparePack);
			} else {
				sort_pack = false;
				parent->m_grf_data->Sort(ComparePackX);
			} break;
	}
}

void MyDataViewCtrl::OnResize(wxSizeEvent &event)
{
	event.Skip(true);
	if (width != GetClientSize().GetWidth()) {
		if (GetColumn(COL_TYPE)->GetWidth() > 170)
			GetColumn(COL_TYPE)->SetWidth(110);
		GetColumn(COL_NAME)->SetWidth(GetClientSize().GetWidth()-140-GetColumn(COL_TYPE)->GetWidth());
		width = GetClientSize().GetWidth();
	}
	if (GetClientSize().GetWidth() >= GetColumn(COL_NAME)->GetWidth() + GetColumn(COL_TYPE)->GetWidth() + 140)
		SetScrollbar(wxHORIZONTAL, 0, 0, 0, true);
}

bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString &file_names)
{
	if (file_names.Count() > 1)
		return false;
	else
		return m_parent->FileOpen(file_names[0]);
}